/*
tasklet 软件, 处理函数 传递 指针参数
 */

#include <linux/init.h>
#include <linux/module.h>
#include <linux/printk.h>

#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/slab.h>

struct tasklet_struct my_tasklet;
struct my_tasklet_data {
    int param1;
    char param2;
};

void my_tasklet_handler(unsigned long data)
{
    struct my_tasklet_data* td = (struct my_tasklet_data*)data;
    int count;
    printk(KERN_INFO "Tasklet received params: %d, %c\n", td->param1, td->param2);

    count = td->param1;
    while(count){
        pr_info("tasklet handler count=%d\n",count--);
        mdelay(1000);
    }
    kfree(td); // 使用后释放内存
}

// 模块初始化函数
static int __init my_module_init(void)
{
    struct my_tasklet_data* td = kmalloc(sizeof(*td), GFP_ATOMIC);
    if (!td) {
        printk(KERN_ERR "Failed to allocate tasklet data\n");
        return -1;
    }
    td->param1 = 10;
    td->param2 = 'A';

    printk(KERN_INFO "Module initialized\n");

    tasklet_init(&my_tasklet, my_tasklet_handler, (unsigned long)td);
    tasklet_schedule(&my_tasklet);
    // mdelay(200);    // 保证 tasklet 先被执行
    pr_info("module init end\n");
    return 0;
}

// 模块退出函数
static void __exit my_module_exit(void)
{
    printk(KERN_INFO "Module exited\n");
    tasklet_kill(&my_tasklet);
}

module_init(my_module_init);
module_exit(my_module_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("liu Jiang");
MODULE_DESCRIPTION("A simple Tasklet example");